Shader Reloader Macro topic
ShaderReloaderMacro
ShaderReloaderMacro is a builtin asset macro that compiles Flutter GPU shader bundles. It
watches a directory of shader sources and, whenever a file changes (add, modify or remove),
locates every *.shaderbundle.json manifest in that directory and re-runs impellerc to
produce a compiled .shaderbundle.
The compiled bundles are written into the configured asset macro output directory (for example
build/shaderbundles), so a running Flutter app can pick up rebuilt shaders on hot reload
without any manual build step — pair it with the onMacroFilesGenerated stream to react
instantly.
The macro is pure Dart (dart:io + process spawn) and has no Flutter dependency.
Features
- ✅ Automatic Recompilation: Re-runs
impellercwhenever any watched shader file changes - ✅ Multi-Manifest Support: Compiles every
*.shaderbundle.jsonmanifest in the watched directory (including nested subdirectories) - ✅ Cross-Platform Compiler Discovery: Locates
impellercfor macOS (arm64/x64), Linux and Windows automatically - ✅ Engine Shader Library: Passes the engine's
shader_libdirectory via--include, so shaders can use framework includes like<flutter_gpu/framebuffer.frag.h> - ✅ Live Push Events: The generated bundle paths are pushed to connected apps through
onMacroFilesGenerated
Setup
Register the macro in your project's macro entrypoint:
await runMacro(
macros: {
'ShaderReloaderMacro': ShaderReloaderMacro.initialize,
},
assetMacros: {
'shaders': [
AssetMacroInfo(
macroName: 'ShaderReloaderMacro',
// The server matches single-level extensions, so `.json`
// also covers `.shaderbundle.json` manifests.
extension: '.vert,.frag,.json',
output: 'build/shaderbundles',
config: const ShaderReloaderConfig().toJson(),
),
],
},
);
Configuration Parameters
macroName
- Type:
String - Required: Yes
- Description: The name of the macro to use. Must be
'ShaderReloaderMacro'.
extension
- Type:
String - Required: Yes
- Description: File extension filter for the watched shader sources. Use something like
'.vert,.frag,.json'to watch shader sources plus manifests.
output
- Type:
String - Required: Yes
- Description: Directory where compiled
.shaderbundlefiles are written (e.g.'build/shaderbundles').
config
- Type:
Map<String, dynamic>? - Required: false
- Description: Configuration object for the ShaderReloaderMacro. Must be converted to JSON
using
.toJson().
ShaderReloaderConfig Options
final config = const ShaderReloaderConfig(
manifestExtension: '.shaderbundle.json',
compilerPath: '/path/to/impellerc',
flutterRoot: '/path/to/flutter',
);
manifestExtension
- Type:
String? - Default:
'.shaderbundle.json' - Description: Suffix that identifies shader bundle manifests within the watched directory.
compilerPath
- Type:
String? - Default:
null - Description: Explicit path to the
impellercexecutable. When set, it takes precedence over all automatic discovery strategies.
flutterRoot
- Type:
String? - Default:
null - Description: Explicit path to the Flutter SDK root used to locate
impellercand the engineshader_libincludes. Takes precedence overFLUTTER_ROOTand ephemeral configs.
Manifest Format
A manifest declares which shader sources belong to a bundle. Each key becomes the shader name,
with its type (vertex or fragment) and source file relative to the manifest:
{
"CubeVertex": {
"type": "vertex",
"file": "cube.vert"
},
"CubeFragment": {
"type": "fragment",
"file": "cube.frag"
}
}
The compiled output keeps the manifest's base name: flutter_example.shaderbundle.json
produces flutter_example.shaderbundle inside the configured output directory.
How it finds impellerc
ShaderReloaderConfig.compilerPathexplicit overrideShaderReloaderConfig.flutterRootexplicit overrideFLUTTER_ROOTenvironment variableFLUTTER_ROOT=inside the project's platform-specific ephemeral config generated by the flutter tool (Flutter-Generated.xcconfigon macOS/iOS,generated_config.cmakeon Linux/Windows)
For each candidate root it probes the engine artifacts directory
bin/cache/artifacts/engine/<target>/impellerc, where <target> matches the host machine
(darwin-arm64/darwin-x64 on macOS, linux-x64 on Linux, windows-x64 on Windows).
Hot Reloading In A Running App
Listen to the generated files stream after connecting and reinitialize your shader library:
onMacroFilesGenerated.listen((files) {
final bytes = File(bundlePath).readAsBytesSync();
library.reinitializeFromBytes(ByteData.sublistView(bytes));
});
Saving any watched shader source now recompiles the bundle and recolors/re-renders the running app without a rebuild.
Classes
- Macro Get started Installation Models Data Class Macro Compute Macro Asset Path Macro Shader Reloader Macro Global Configuration Write New Macro Capability
- Macro used to attach metadata to a Dart declaration.